
// VS_BEGIN
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aCoord;
layout (location = 2) in vec3 aNormal;
layout (location = 3) in vec3 aTangent;
layout (location = 4) in vec3 aBitangent;

uniform mat4 u_model;
uniform mat3 u_modelT;

layout (std140) uniform EngineUBO
{
    mat4 u_view;
    mat4 u_project;
    vec3 u_camPos;
};

out vec3 g_normal;

void main() {
    gl_Position = u_model * vec4(aPos, 1.0f);
    g_normal = normalize(u_modelT * aNormal);
}
// VS_END

// GS_BEGIN
#version 330 core 
layout (triangles) in;
layout (line_strip, max_vertices = 18) out;

layout (std140) uniform EngineUBO
{
    mat4 u_view;
    mat4 u_project;
    vec3 u_camPos;
};

layout (std140) uniform LightUBO
{
    mat4 u_lights[64];
    int u_lightNum;
};

in vec3 g_normal[];

out vec3 g_color;

uniform sampler2D u_positionRT;
uniform sampler2D u_normalRT;
uniform sampler2D u_tangentRT;
uniform sampler2D u_depthRT;
uniform sampler2D u_albedoRT;

bool Is0_1(float x) {
    return 0.0f < x && x < 1.0f;
}

void DrawNormal(int index) {
    gl_Position = u_project * u_view * (gl_in[index].gl_Position + vec4(g_normal[index], 0.0f) * 1.0f);
    vec3 viewPos = gl_Position.xyz / gl_Position.w * 0.5f + vec3(0.5f);
    float depth = texture(u_depthRT, viewPos.xy).r;
    if (viewPos.z > depth) {
        g_color = vec3(1.0f, 0.0f, 0.0f);
    } else {
        g_color = vec3(1.0f);
    }
    EmitVertex();
    gl_Position = u_project * u_view * gl_in[index].gl_Position;
    EmitVertex();
    EndPrimitive();
}

void DrawLine(int index) {
    vec3 camDir = normalize(gl_in[index].gl_Position.xyz - u_lights[0][0].xyz);
    vec3 refDir = normalize(reflect(camDir, g_normal[index]));
    gl_Position = u_project * u_view * gl_in[index].gl_Position;
    g_color = vec3(0.0f, 1.0f, 0.0f);
    EmitVertex();
    gl_Position = u_project * u_view * (gl_in[index].gl_Position + vec4(refDir, 0.0f) * 1.0f);
    g_color = vec3(0.0f, 1.0f, 0.0f);
    EmitVertex();
    EndPrimitive();
}

void main() {
    // DrawLine(0);
    // DrawLine(1);
    // DrawLine(2);
    DrawNormal(0);
    DrawNormal(1);
    DrawNormal(2);
}
// GS_END

// FS_BEGIN
#version 330 core 

// Light Packet:
// position.x position.y position.z type(PointLight: 0; DirectLight: 1; AmbientSphereLight: 2)
// color.r    color.g    color.b    strength
// direct.x   direct.y   direct.z   unuse
// unuse      unuse      unuse      unuse
layout (std140) uniform LightUBO
{
    mat4 u_lights[64];
    int u_lightNum;
};

layout (std140) uniform EngineUBO
{
    mat4 u_view;
    mat4 u_project;
    vec3 u_camPos;
};

uniform samplerCube u_irradianceMap; 

in vec3 g_color;

out vec4 FragColor;

void main() {
    FragColor = vec4(g_color, 1.0f);
}
// FS_END
